#ifndef MD5_COMPUTER_H_
#define MD5_COMPUTER_H_

#define DEBUG 0

#include <stdint.h>
#include <stdio.h>

typedef unsigned char 			u8;
typedef unsigned int 			u32;
typedef uint64_t				u64;
typedef uintptr_t				uptr;

#define MAX_PASSW_LENGTH		16
#define MAX_STR_LENGTH			128
#define MAX_SALT_LENGTH			16

#define ALPHABET				"0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
#define ALPHALEN				62

#define F(x, y, z)			   	(((x) & (y)) | ((~x) & (z)))
#define G(x, y, z)			   	(((x) & (z)) | ((y) & (~z)))
#define H(x, y, z)			   	((x) ^ (y) ^ (z))
#define I(x, y, z)			   	((y) ^ ((x) | (~z)))

#define MIN(x, y)				((x) > (y) ? (y) : (x))

typedef struct {
	u32 A;
	u32 B;
	u32 C;
	u32 D;
	u32 total[2];
	u32 buflen;
	union {
		u8 buffer[128];
		u32 buffer32[32];
	};
} md5_ctx;

typedef struct {
	int blocks; // Total number of blocks.
	int threads; // Threads per block.
} grid_size;

typedef struct {
	int len; // Size of the dictionary in bytes.
	int word_cnt; // Number of words in the dictionary.
} dict_size;

typedef struct {
	int len; // Length of the passwords generated in brute force mode.
	long alphabet_size; // Number of possible passwords of length len.
} bruteforce_size;


void break_dictionary(grid_size gs, dict_size ds, u8 *dict, u8 *salt, u8 *target_hash, u8 *result_key);

void brute_force(int len, grid_size gs, u8 *salt, u8 *target_hash, u8 *result_key);
                             
#endif           
